#include "layermodel.hpp"

Map::Map(int w, int h){
    Resize(w, h);
}

void Map::Resize(int w, int h){
    map_.resize(w);
    for(int i=0;i<map_.size();i++)
        map_[i].resize(h, nullptr);
}

int Map::GetWidth() const{
    return map_.size();
}

int Map::GetHeight() const{
    return map_[0].size();
}


LayerModel::LayerModel(int width, int height){
    _map.Resize(width, height);
}

void LayerModel::AddObject(Object* object){
    assert(object->GetPosition().x<_map.GetWidth() && object->GetPosition().y<_map.GetHeight());
    SDL_Point pos = object->GetPosition();
    if(object->GetType()==ObjType::CREATURE){   // 如果是生物，放在生物列表中
        _creatures.push_back(object);
    }else{
        _objects.push_back(object);
        Object* obj = _map.map_[pos.x][pos.y];
        if(!obj){   // 如果当前位置不存在任何东西，那我们只能放置墙或者地面
            if(object->GetType()!=ObjType::GROUND && object->GetType()!=ObjType::WALL)
                SDL_Log("{%s}:[%d]:only wall and ground can be set at null cell", __FILE__, __LINE__);
            else
                _map.map_[pos.x][pos.y] = object;
        }else{  // 如果当前位置存在物体
            if(obj->GetType()==ObjType::GROUND){ // 如果当前位置是地面，则将物体放到地面上
                dynamic_cast<Ground*>(obj)->Add(object);
            }else{ // 如果当前位置不是地面，则报一个警告
                SDL_Log("(%d, %d) already have something but not Ground", pos.x, pos.y);
            }
        }
    }
}

void LayerModel::RemoveObject(Object* object){
    int i;
    for(i=0;i<_objects.size();i++)
        if(_objects[i]==object){
            break;
        }
    _objects.erase(_objects.begin()+i);
}

Object* LayerModel::GetObjAt(int x, int y){
    return _map.map_.at(x).at(y);
}

Object* LayerModel::GetCreatureAt(int x, int y){
    for(Object* obj : _creatures)
        if(obj->GetPosition().x==x && obj->GetPosition().y==y)
            return obj;
    return nullptr;
}

void LayerModel::Draw(int x, int y){
    for(Object* obj : _objects){
        obj->Move(x, y);
        obj->Draw();
        obj->Move(-x, -y);
    }
}

const Map& LayerModel::GetMap() const{
    return _map;
}

void LayerModel::Update(){
    for(int i=0;i<_map.GetWidth();i++)
        for(int j=0;j<_map.GetHeight();j++)
            _map.map_[i][j] = nullptr;
    for(Object* o : _objects)
        if(o->GetType()==ObjType::WALL || o->GetType()==ObjType::GROUND || o->GetType()==ObjType::CREATURE)
            _map.map_[o->GetPosition().x][o->GetPosition().y] = o;
}
